package com.hzdesk.media.koreabatchmatvector.service;

import android.annotation.SuppressLint;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.media.MediaMetadataRetriever;
import android.media.ThumbnailUtils;
import android.media.projection.MediaProjection;
import android.net.Uri;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.util.Log;
import android.widget.Toast;

import com.hzdesk.media.koreabatchmatvector.R;
import com.hzdesk.media.koreabatchmatvector.base.MyClientApplication;
import com.hzdesk.media.koreabatchmatvector.bean.Memory;
import com.hzdesk.media.koreabatchmatvector.bean.VideoFile;
import com.hzdesk.media.koreabatchmatvector.bean.XmlMeetingBean;
import com.hzdesk.media.koreabatchmatvector.bean.XmlUserBean;
import com.hzdesk.media.koreabatchmatvector.bean.XmlVideoFile;
import com.hzdesk.media.koreabatchmatvector.config.AppConfig;
import com.hzdesk.media.koreabatchmatvector.config.RxBusUtil;
import com.hzdesk.media.koreabatchmatvector.dao.MemoryDaoUtils;
import com.hzdesk.media.koreabatchmatvector.dao.VideoFileDaoUtils;
import com.hzdesk.media.koreabatchmatvector.screenrecord.AudioEncodeConfig;
import com.hzdesk.media.koreabatchmatvector.screenrecord.Notifications;
import com.hzdesk.media.koreabatchmatvector.screenrecord.ScreenRecorder;
import com.hzdesk.media.koreabatchmatvector.screenrecord.Utils;
import com.hzdesk.media.koreabatchmatvector.screenrecord.VideoEncodeConfig;
import com.hzdesk.media.koreabatchmatvector.utils.FileUtil;
import com.hzdesk.media.koreabatchmatvector.utils.MyToastUtils;
import com.hzdesk.media.koreabatchmatvector.utils.RxBus;
import com.hzdesk.media.koreabatchmatvector.utils.SharedPreferencesUtils;
import com.hzdesk.media.koreabatchmatvector.utils.XMLUtil;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.UUID;

import static android.Manifest.permission.RECORD_AUDIO;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;

/**
 * function:屏幕录制
 * <p>
 * Created by Administrator on 2018/8/2.
 * <p>
 * 存储目录-------------
 * ----------Deskmedia
 * -------------会议1
 * -----------------会议1-1
 * -----------------会议1-1.mp4
 * -----------------会议1-1.xml
 * -----------------会议1-1.jpg
 * -----------------会议1-1.png
 * -----------------会议1-1.awr
 * -------------会议1-2
 */

public class ScreenRecordService extends Service {
    private String TAG = "ScreenRecordService";
    private RecordBinder recordBinder = new RecordBinder();
    private ScreenRecorder mRecorder;
    private Notifications mNotifications;
    private MediaProjection mMediaProjection;
    private Context mContext;

    private boolean isRecordAudio = false;

    private boolean isStopRecord=false;


    private int BitmapCompressWidth = 800;            //图片压缩宽度
    private int BitmapCompressHight = 480;            //图片压缩高度
    private List<XmlVideoFile> xmlVideoFileList;        //xml文件的file集合
    private List<Long> startTimeList;                   //开始时间点
    private List<Long> stopTimeList;                    //停止时间点
    private List<VideoFile> videoFileList;              //videoFile集合
    private List<XmlUserBean> xmlUserBeanList;
    private String XmlPath;                             //xml文件最初保存路径
    private String myUUID;
    private int i = 1;
    private int j = 1;
    private String meetingname;                             //会议名称
    private String suffixName;                              //分段后缀

    private String meetingdirpath;                       //会议路径           /Deskmedia/会议1
    private String dirpath;                              //保存文件的文件夹路径 /Deskmedia/会议1/会议1-1

    private String realname;                               //第二名称

    private VideoEncodeConfig videoEncodeConfig;
    private AudioEncodeConfig audioEncodeConfig;

    private RecordCallback recordCallback;


    @Override
    public void onCreate() {
        super.onCreate();
        mContext = this;
        xmlVideoFileList = new ArrayList<>();
        startTimeList = new ArrayList<>();
        stopTimeList = new ArrayList<>();
        videoFileList = new ArrayList<>();
        mNotifications = new Notifications(getApplicationContext());
        isRecordAudio = SharedPreferencesUtils.getRecordMode(getApplicationContext()) == 1 ? true : false;
        getFileSuffix();

    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return recordBinder;
    }

    public class RecordBinder extends Binder {
        public ScreenRecordService getService() {
            return ScreenRecordService.this;
        }
    }

    public void setRecordCallback(RecordCallback recordCallback) {
        this.recordCallback = recordCallback;
    }

    public void setmMediaProjection(MediaProjection mMediaProjection) {
        this.mMediaProjection = mMediaProjection;
    }
    // 开始录制
    public void startScreenRecord(){
        startRecord(true);
    }
    //分段录制
    public void subSectionScreenRecord(){
        startRecord(false);
    }

    private void startRecord(boolean isFirst) {
        videoEncodeConfig = new VideoEncodeConfig(1920, 1080, 16000000, 60, 30, "OMX.realtek.video.enc.avc", "video/avc", Utils.toProfileLevel(""));
        if (isRecordAudio) {
            audioEncodeConfig = new AudioEncodeConfig("OMX.google.aac.encoder", "audio/mp4a-latm", 8000, 44100, 1, 1);
        }
        MyClientApplication.setIsRecording(true);
        if (getSurplusSize()) {
            if (isFirst) {
                MyClientApplication.setStartTime(new Date().getTime());
                myUUID = getMyUUID();
                startTimeList.add(0L);
                myUUID = getMyUUID();
                //更新文件名称
                j = 1;
                suffixName = i + "-" + j;
                j++;

                //会议1
                meetingname = getMeetingname(mContext) + i;

                Log.d(TAG, "new  meetingName:" + suffixName);
            } else {
                startTimeList.add(getCurrentTime() - MyClientApplication.getStartTime());
                suffixName = i + "-" + j;
                Log.d(TAG, "subsection meetingName:" + suffixName);
                j++;
            }

            realname = FileUtil.setFileName();
            MyClientApplication.setIsRecording(true);
            //开启分段线程
            //new SubSectionThread().start();
            fileisExit(mContext);
            //保存开始时间

            showToast(R.string.start_record);

            meetingdirpath = getStoragePath(mContext) + "/" + meetingname;
            Log.d(TAG + "1", meetingdirpath);

            dirpath = meetingdirpath + "/" + getFilename(mContext);
            Log.d(TAG + "2", dirpath);
            //视频文件路径       /Deskmedia/会议1/会议1-1/会议1-1.mp4
            String videopath = dirpath + "/" + getFilename(mContext) + AppConfig.FILE_TYPE_MP4;
            Log.d(TAG + "3", videopath);
            //音频文件路径       /Deskmedia/会议1/会议1-1/会议1-1.awr
            String awrpath = dirpath + "/" + getFilename(mContext) + AppConfig.FILE_TYPE_AMR;
            Log.d(TAG + "4", awrpath);
            //创建文件夹
            FileUtil.createDir(new File(meetingdirpath));
            FileUtil.createDir(new File(dirpath));
            //创建会议描述文件
            createMeetingXml();

            //创建视频文件
            File file = new File(videopath);
            //FileUtil.createNewFile(file);
            mRecorder = newRecorder(mMediaProjection, videoEncodeConfig, audioEncodeConfig, file);
            startRecorder();

        }


    }


    private ScreenRecorder newRecorder(MediaProjection mediaProjection, VideoEncodeConfig video,AudioEncodeConfig audio, File output) {
        ScreenRecorder r = new ScreenRecorder(video, audio,1, mediaProjection, output.getAbsolutePath());
        r.setCallback(new ScreenRecorder.Callback() {
            long startTime = 0;

            @Override
            public void onStop(Throwable error) {
                Log.d(TAG+"record","onStop");
                if (error != null) {
                    error.printStackTrace();
                    output.delete();
                } else {
                    Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE)
                            .addCategory(Intent.CATEGORY_DEFAULT)
                            .setData(Uri.fromFile(output));
                    sendBroadcast(intent);
                }
            }

            @Override
            public void onStart() {
                mNotifications.recording(0);
                Log.d(TAG+"record","onStart");
            }

            @Override
            public void onRecording(long presentationTimeUs) {
                if (startTime <= 0) {
                    startTime = presentationTimeUs;
                }
                long time = (presentationTimeUs - startTime) / 1000;
                mNotifications.recording(time);
            }
        });
        return r;
    }

    private void startRecorder() {
        if (mRecorder == null) return;
        mRecorder.start();
        // moveTaskToBack(true);
    }

    private void cancelRecorder() {
        if (mRecorder == null) return;
        Toast.makeText(this, "Permission denied! Screen recorder is cancel", Toast.LENGTH_SHORT).show();
        stopRecorder(false);
    }

    public void stopRecorder(boolean isSubSection) {
        MyClientApplication.setIsRecording(false);
        mNotifications.clear();
        if (mRecorder != null) {
            mRecorder.quit();
        }
        mRecorder = null;
        String name = getFilename(mContext);
        getFragemAtTime(dirpath + "/" + name);
        try {
            long size = FileUtil.getFileSize(new File(dirpath));
            videoFileList.add((new VideoFile(null, name, new File(name + AppConfig.FILE_TYPE_MP4).lastModified(), getStoragePath(mContext), size, realname, myUUID, meetingname, MyClientApplication.getStartTime())));
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (isSubSection) {
            //startRecord(false);
            if (recordCallback!=null){
                recordCallback.SubSectionRecord();
            }

        } else {
            //会议名称+1
            i++;
            isStopRecord=true;
            //生成xml文件
          /*  for (int i = 0; i < videoFileList.size(); i++) {
                xmlVideoFileList.add(new XmlVideoFile(videoFileList.get(i).getName(), videoFileList.get(i).getSecondname(), startTimeList.get(i), stopTimeList.get(i)));
            }
            XmlPath = dirpath + "/" + getFilename(mContext) + AppConfig.FILE_TYPE_XML;
            XMLUtil.CreatXMLFile(MyClientApplication.getmPathBeanList(), xmlVideoFileList, xmlUserBeanList, XmlPath, getCurrentTime() - MyClientApplication.getStartTime());
            Iterator<?> it = MyClientApplication.getmPathBeanList().iterator();
            while (it.hasNext()) {
                it.next();
                it.remove();
            }*/
            showLoadDialog();
            saveXmlFile();
            showToast(R.string.stop_record);
        }

    }

    private boolean hasPermissions() {
        PackageManager pm = getPackageManager();
        String packageName = getPackageName();
        int granted = (isRecordAudio ? pm.checkPermission(RECORD_AUDIO, packageName) : PackageManager.PERMISSION_GRANTED)
                | pm.checkPermission(WRITE_EXTERNAL_STORAGE, packageName);
        return granted == PackageManager.PERMISSION_GRANTED;
    }

    /**
     * 获取视频第一帧
     */
    @SuppressLint("StaticFieldLeak")
    private void getFragemAtTime(String path) {
        //视频文件路径         /Deskmedia/会议1/会议1-1/会议1-1.mp4
        String videopath = path + AppConfig.FILE_TYPE_MP4;

        //缩略图文件路径       /Deskmedia/会议1/会议1-1/会议1-1.jgp
        String jpgpath = path + AppConfig.FILE_TYPE_JPG;
        Log.e(TAG,"getFragemAtTime:"+jpgpath);

        if (FileUtil.isFileExist(videopath)) {
            new Thread() {
                @Override
                public void run() {
                    super.run();
                    Bitmap bitmap = null;
                    MediaMetadataRetriever mediaMetadataRetriever = new MediaMetadataRetriever();
                    File videofile=new File(videopath);
                    mediaMetadataRetriever.setDataSource(videofile.getAbsolutePath());
                    bitmap = mediaMetadataRetriever.getFrameAtTime();
                    bitmap = ThumbnailUtils.extractThumbnail(bitmap, BitmapCompressWidth, BitmapCompressHight, ThumbnailUtils.OPTIONS_RECYCLE_INPUT);
                    if (bitmap != null) {
                        File file = new File(jpgpath);
                        try {
                            BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file));
                            bitmap.compress(Bitmap.CompressFormat.JPEG, 50, bos);
                            bos.flush();
                            bos.close();
                            mediaMetadataRetriever.release();
                            Log.e(TAG, "getFragemAtTime success:"+jpgpath);
                            dismissLoadDialog();
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    } else {
                        Log.e(TAG, "getFragemAtTime fail:"+jpgpath);
                        dismissLoadDialog();
                    }
                }
            }.start();

        }

    }

    /**
     * 生成会议信息文件
     * path: /Deskmedia/会议1/会议1.xml
     */
    private void createMeetingXml() {
        XmlMeetingBean xmlMeetingBean = new XmlMeetingBean(MyClientApplication.getStartTime(), meetingname);
        String path = meetingdirpath + "/" + meetingname + AppConfig.FILE_TYPE_XML;
        XMLUtil.CreatMeetingXml(xmlMeetingBean, path);


    }


    /**
     * 把文件复制到所有文件夹下（xml文件保存在最后录制的一段视频文件目录下，所以需要把xml文件复制到其他段的视频目录下）
     */
    private void saveXmlFile() {
        Log.e(TAG, "saveXmlFile--------");
        for (int i = 0; i < videoFileList.size(); i++) {


            //水印文件路径       /Deskmedia/会议1/会议1-1/会议1-1.png
            String pngPath = videoFileList.get(i).getPath() + "/" + videoFileList.get(i).getMeetingName() + "/" + videoFileList.get(i).getName() + "/" + videoFileList.get(i).getName() + AppConfig.FILE_TYPE_PNG;

            //批注文件路径       /Deskmedia/会议1/会议1-1/会议1-1.xml
            String xmlPath = videoFileList.get(i).getPath() + "/" + videoFileList.get(i).getMeetingName() + "/" + videoFileList.get(i).getName() + "/" + videoFileList.get(i).getName() + AppConfig.FILE_TYPE_XML;

            //拷贝水印文件
            if (FileUtil.isFileExist(SharedPreferencesUtils.getWaterMarkPath(mContext))) {
                Log.e(TAG, "存在-=---------");

                try {
                    FileUtil.copyFile(new File(SharedPreferencesUtils.getWaterMarkPath(mContext)), pngPath);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                Log.e(TAG, "不存在-=---------");
            }
            //拷贝批注文件
            /*if (i == (videoFileList.size() - 1)) {

            } else {
                try {
                    FileUtil.copyFile(new File(XmlPath), xmlPath);
                } catch (IOException e) {
                    e.printStackTrace();
                }

            }*/
            saveFiletoDB(videoFileList.get(i));
        }
        //dismissLoadDialog();
    }

    /**
     * 保存文件到数据库
     */
    private void saveFiletoDB(VideoFile videoFile) {
        Log.e(TAG, "saveFiletoDB-------");
        try {
            long size = FileUtil.getFileSize(new File(dirpath));
            VideoFile videoFile2 = new VideoFile(null, videoFile.getName(), new File(dirpath + AppConfig.FILE_TYPE_MP4).lastModified(), videoFile.getPath(), size, videoFile.getSecondname(), videoFile.getMeetingGroup(), videoFile.getMeetingName(), videoFile.getMeetingTime());
            VideoFileDaoUtils videoFileDaoUtils = new VideoFileDaoUtils(this);
            videoFileDaoUtils.insertVideoFile(videoFile2);
            updataMemory(size);
            //dismissLoadDialog();
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    // todo 更改内存使用情况
    private void updataMemory(long size) {
        double new_used = (double) size / 1048576;
        MemoryDaoUtils memoryDaoUtils = new MemoryDaoUtils(this);
        Memory memory = memoryDaoUtils.queryAllMemory().get(1);
        double old_uesd = (double) memory.getSize() / 1048576;
        memory.setSize(new_used + old_uesd);
        memoryDaoUtils.updateMemory(memory);
    }

    // todo 检测内存
    public boolean getSurplusSize() {
        MemoryDaoUtils memoryDaoUtils = new MemoryDaoUtils(this);
        List<Memory> list = memoryDaoUtils.queryAllMemory();

        double total = 0, used = 0;
        for (Memory memory : list) {
            if (memory.getStorageType().equals(AppConfig.MEMORY_TYPE_TOTAL_SIZE)) {
                total = memory.getSize();
            }
            if (memory.getStorageType().equals(AppConfig.MEMORY_TYPE_USED_SIZE)) {
                used = memory.getSize();
            }
        }
        double a = total - used;
        if (a < 0 || a < 5120) {
            return false;
        } else {
            return true;
        }
    }

    // 获取当前时间
    private long getCurrentTime() {
        return new Date().getTime();
    }

    //判断存数路径是否存在
    private void fileisExit(Context mContext) {
        String VideoSavePath = (String) SharedPreferencesUtils.getInstance(mContext).getDate(AppConfig.Video_SAVE_PATH, "String");
        if (FileUtil.isFileExist(VideoSavePath)) {
            FileUtil.createDir(new File(AppConfig.DESKMEDIAFILE));
            if (VideoSavePath.equals("")) {
                SharedPreferencesUtils.getInstance(mContext).putDate(AppConfig.Video_SAVE_PATH, VideoSavePath);
            }
        }
    }

    //获取存储路径
    private String getStoragePath(Context mContext) {
        String videoSavePath = SharedPreferencesUtils.getVideoSavePath(mContext);
        //会议名称
        //String meetingName = SharedPreferencesUtils.getMeetingName(mContext);
        return videoSavePath;
    }

    /**
     * 获取会议名
     *
     * @param mContext
     * @return
     */
    private String getMeetingname(Context mContext) {
        String meetingName = SharedPreferencesUtils.getMeetingName(mContext);
        return meetingName;
    }

    /**
     * 获取会议分段后缀
     *
     * @return 1-1
     */
    private void getFileSuffix() {
        String name = i + "-" + j;
        VideoFileDaoUtils videoFileDaoUtils = new VideoFileDaoUtils(ScreenRecordService.this);
        List<VideoFile> list = videoFileDaoUtils.queryAllVideoFile();
        boolean ishas = false;
        for (VideoFile videoFile : list) {
            String s = SharedPreferencesUtils.getMeetingName(ScreenRecordService.this) + i + "-" + j;
            if (videoFile.getName().equals(s)) {
                Log.e(TAG, "haved name:" + i + "-" + j);
                ishas = true;
                break;
            }

        }
        if (ishas) {
            i++;
            getFileSuffix();
        } else {
            Log.e(TAG, "no has name:" + i + "-" + j);
        }


    }

    /**
     * 获取带有时间名称
     *
     * @return
     */
    private String getFilename(Context mContext) {
        return SharedPreferencesUtils.getMeetingName(mContext) + suffixName;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }


    private void showToast(int id) {
        MyToastUtils.ShortToaseShow(ScreenRecordService.this, getString(id));
    }

    private void showLoadDialog() {
        RxBus.getInstance().send(RxBusUtil.SHOW_LOAD_DIALOG);

    }

    private void dismissLoadDialog() {
        RxBus.getInstance().send(RxBusUtil.DISMISS_LOAD_DIALOG);

    }

    /**
     * 分段计时线程，达到分段时长执行分段
     */
    private class SubSectionThread extends Thread {
        //private long time = SharedPreferencesUtils.getSubSectionTime(RecordService.this);
        private long time = 30 * 1000;

        @Override
        public void run() {
            super.run();
            try {
                Thread.sleep(time);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!isStopRecord){
                stopRecorder(true);
            }
        }
    }

    private String getMyUUID() {
        UUID uuid = UUID.randomUUID();
        String s = uuid.toString();
        return s;
    }


    public interface RecordCallback{
        void SubSectionRecord();

    }


}
